package com.lmy.springCloud.controller;

import com.lmy.springCloud.entity.Member;
import com.lmy.springCloud.utils.Result;
import com.lmy.springCloud.utils.ResultEnum;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.client.ServiceInstance;
import org.springframework.cloud.client.discovery.DiscoveryClient;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.annotation.Resource;
import java.util.List;

@RestController
@Slf4j
public class MemberConsumerController {

    /*
        1.RestTemplate是Spring提供的用于访问Rest服务的模板类(类似JdbcTemplate)
        2.RestTemplate提供了多种便捷访问远程HTTP服务的方法
        3.可以这样理解：之前是通过浏览器发送请求到服务端。现在需要在服务端发送请求到另一个服务，需要使用RestTemplate
     */
    //定义要请求的服务地址
//    public static final String MEMBER_SERVICE_PROVIDER_URL = "http://localhost:9090";
    /*
        1.MEMBER-SERVICE-PROVIDER 就是服务提供方注册到EurekaServer的别名
        2.也就是服务提供方(集群)对外暴露的名称为 MEMBER-SERVICE-PROVIDER
        3.MEMBER-SERVICE-PROVIDER 目前有两个 Availability Zones:
          member-service-provider:9090 和 member-service-provider:9091
          需要增加一个注解@LoadBanlanced 赋予 RestTemplate负载均衡的能力，
          也就是说会根据负载均衡算法来选择某个服务去访问，默认是轮询算法，
          当然也可以自己配置负载均衡算法。
        4.Ribbon和Eureka整合后consumer直接调用服务而不用再关心地址和端口号，且该服务还有负载均衡功能
     */
    public static final String MEMBER_SERVICE_PROVIDER_URL = "http://MEMBER-SERVICE-PROVIDER";

    //装配RestTemplate
    @Resource
    private RestTemplate restTemplate;

    //装配DiscoveryClient
    @Resource
    private DiscoveryClient discoveryClient;

    @PostMapping(value = "/consumer/saveMember")
    public Result saveMember(Member member) {
        log.info("service_consumer_member={}", member);
        //请求会员中心微服务的/saveMember
        //postForObject 以对象的方式发送请求，即json对象
        Result result = restTemplate.postForObject(MEMBER_SERVICE_PROVIDER_URL + "/saveMember",
                member, Result.class);
        return result;
    }

    @GetMapping(value = "/consumer/getMemberById/{id}")
    public Result getMemberById(@PathVariable("id") Long id) {
        //请求会员中心微服务的/saveMember
        //这里通过restTemplate调用服务提供模块的接口，就是一个远程调用即rpc(remote procedure call)
        Result result = restTemplate.getForObject(MEMBER_SERVICE_PROVIDER_URL + "/getMemberById/" + id, Result.class);
        return result;
    }

    @GetMapping(value = "/consumer/discovery")
    public Result discovery() {
        //拿到EurekaServer存储的所有服务注册信息
        List<String> services = discoveryClient.getServices();
        //遍历服务
        for (String service : services) {
            log.info("==============服务名={}=================", service);
            //通过服务名，获取对应的服务实例，可能有多个
            List<ServiceInstance> instances = discoveryClient.getInstances(service);
            for (ServiceInstance instance : instances) {
                log.info("id={}, host={},port={},uri={}",
                        instance.getServiceId(), instance.getHost(), instance.getPort(), instance.getUri());

            }
        }
        return Result.info(ResultEnum.OK, discoveryClient);
    }

}
